package com.neusoft.hifly.netty.socket;

import org.springframework.kafka.core.KafkaTemplate;

import com.neusoft.hifly.core.log.Log;
import com.neusoft.hifly.netty.config.NettyConfig;
import com.neusoft.hifly.netty.socket.handler.SocketServerInitialzer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * Title: Netty服务
 * <p>
 * Description: Netty Socket服务
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 辽宁畅通数据通信有限公司
 * 
 * @author
 * @version 1.0.0
 */
public class SocketServer {
	/**
	 * 启动Socket服务
	 * 
	 * @param nettyConfig
	 *            配置
	 * @param kafkaTemplate
	 *            kafka
	 * @throws Exception
	 *             异常
	 */
	public void start(NettyConfig nettyConfig, KafkaTemplate<String, Object> kafkaTemplate) throws Exception {
		//负责接收客户端的连接的线程。线程数设置为1即可，netty处理链接事件默认为单线程，过度设置反而浪费cpu资源
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		//负责处理数据传输的工作线程。线程数默认为CPU核心数乘以2
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap server = new ServerBootstrap();
			server.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
					//在ServerChannelInitializer中初始化ChannelPipeline责任链，并添加到serverBootstrap中
					.childHandler(new SocketServerInitialzer(kafkaTemplate))
					//标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度
					.option(ChannelOption.SO_BACKLOG, 1024)
					//是否启用心跳保活机制
					.childOption(ChannelOption.SO_KEEPALIVE, true);

			// 输出日志
			if (nettyConfig.isLogEnabled()) {
				server.handler(new LoggingHandler(LogLevel.INFO));
			}

			//绑定端口后，开启监听
			ChannelFuture future = server.bind(nettyConfig.getSocketPort()).sync();
			Log.info("Socket Server 启动成功! " + future.channel().localAddress());
			//等待服务监听端口关闭
			future.channel().closeFuture().sync();
		} finally {
			//释放资源
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}
}
